//
//  TranscriptController.swift
//  hello
//
//  Created by 赵康 on 2024/11/11.
//

import Fluent
import Redis
import Vapor

struct TranscriptController: RouteCollection {
  func boot(routes: RoutesBuilder) throws {
    let transcripts = routes.grouped("\(RouteEnum.transcripts.rawValue)")
    let protected = transcripts.grouped(AuthMiddleware())
    protected.get("\(RouteEnum.fetch.rawValue)", ":audioID", use: getTranscriptsByAudio)
    protected.post("feedback", ":audioID", use: submitTranscriptFeedback)
    
    // Add public endpoint for transcript sharing
    transcripts.get("public", ":audioID", use: getPublicTranscripts)
  }
  struct PaginatedTranscriptResponse: Content {
    let items: [Transcript]
    let metadata: PageMetadata

    struct PageMetadata: Content {
      let page: Int
      let per: Int
      let total: Int
    }
  }
  
  // New public endpoint for transcript sharing
  @Sendable
  func getPublicTranscripts(req: Request) async throws -> PaginatedTranscriptResponse {
    LogManager.shared.info("开始处理公共字幕请求", context: "audioID: \(req.parameters.get("audioID", as: String.self) ?? "未知")")
    
    guard let audioID = req.parameters.get("audioID", as: UUID.self) else {
      LogManager.shared.error("无效的音频ID格式", context: "参数值: \(req.parameters.get("audioID") ?? "空")")
      throw Abort(.badRequest, reason: "无效的音频 ID")
    }

    // 检查是否是系统音频
    let systemAudioID = UUID(uuidString: "00000000-0000-0000-0000-000000000000")!
    if audioID == systemAudioID {
      LogManager.shared.warning("尝试访问系统音频", context: "audioID: \(audioID)")
      throw Abort(.notFound, reason: "Audio not found")
    }

    // 修复获取分页参数的方式，正确处理可选参数
    let page: Int
    if let pageParam = req.query[Int.self, at: "page"] {
      page = pageParam
    } else {
      page = 1
    }
    
    let per: Int
    if let perParam = req.query[Int.self, at: "per"] {
      per = min(perParam, 100) // 限制最大每页条数
    } else {
      per = 100
    }
    
    LogManager.shared.debug("分页参数", context: "page: \(page), per: \(per)")
    
    // 计算总记录数
    let total = try await Transcript.query(on: req.db)
      .filter(\.$audio.$id == audioID)
      .filter(\.$isDeleted == false)
      .count()

    // 构建缓存键
    let cacheKey = CacheConfig.KeyBuilder.publicTranscriptsByAudio(
      audioID: audioID,
      page: page,
      per: per,
      total: total
    )
    
    // 尝试从缓存获取
    if let cachedResponse = try? await req.cache.get(
      forKey: cacheKey,
      as: PaginatedTranscriptResponse.self,
      from: req.redis
    ) {
      LogManager.shared.debug("命中缓存", context: "audioID: \(audioID)")
      return cachedResponse
    }

    // 确认音频存在
    guard let audio = try await Audio.find(audioID, on: req.db), !audio.isDeleted! else {
      LogManager.shared.warning("音频不存在或已删除", context: "audioID: \(audioID)")
      throw Abort(.notFound, reason: "Audio not found")
    }

    // 获取分页数据
    let transcripts = try await Transcript.query(on: req.db)
      .filter(\.$audio.$id == audioID)
      .filter(\.$isDeleted == false)
      .sort(\.$startTime, .ascending)
      .offset((page - 1) * per)
      .limit(per)
      .all()

    LogManager.shared.info("成功获取字幕数据", context: """
      audioID: \(audioID)
      字幕数量: \(transcripts.count)
    """)

    // 构建响应数据
    let response = PaginatedTranscriptResponse(
      items: transcripts,
      metadata: .init(
        page: page,
        per: per,
        total: total
      )
    )

    // 缓存结果
    do {
      try await req.cache.set(
        response,
        forKey: cacheKey,
        duration: CacheConfig.Duration.medium,
        type: .transcript,
        on: req.redis
      )
      LogManager.shared.info("成功缓存公共字幕数据", context: "audioID: \(audioID)")
    } catch {
      LogManager.shared.error("缓存公共字幕信息失败", context: "\(error)")
    }

    return response
  }
  
  @Sendable
  func getTranscriptsByAudio(req: Request) async throws -> PaginatedTranscriptResponse {
    let userID = try req.authenticatedUserID

    guard let audioID = req.parameters.get("audioID", as: UUID.self) else {
      throw Abort(.badRequest, reason: "Invalid audio ID")
    }

    // 检查是否是系统音频
    let systemAudioID = UUID(uuidString: "00000000-0000-0000-0000-000000000000")!
    if audioID == systemAudioID {
      throw Abort(.notFound, reason: "Audio not found")
    }

    // 获取分页参数，默认第1页，每页20条
    let page = try req.query.get(Int.self, at: "page")
    let per = try req.query.get(Int.self, at: "per")
    // 计算总记录数
    let total = try await Transcript.query(on: req.db)
      .filter(\.$audio.$id == audioID)
      .filter(\.$isDeleted == false)
      .count()

    // 构建缓存键
    let cacheKey = CacheConfig.KeyBuilder.transcriptsByAudio(
      audioID: audioID,
      page: page,
      per: per,
      total: total,
      userID: userID
    )
    // 尝试从缓存获取
    if let cachedResponse = try? await req.cache.get(
      forKey: cacheKey,
      as: PaginatedTranscriptResponse.self,
      from: req.redis
    ) {
      return cachedResponse
    }

    // 确认音频存在
    guard (try await Audio.find(audioID, on: req.db)) != nil else {
      throw Abort(.notFound, reason: "Audio not found")
    }

    // 获取分页数据
    let transcripts = try await Transcript.query(on: req.db)
      .filter(\.$audio.$id == audioID)
      .filter(\.$isDeleted == false)
      .sort(\.$startTime, .ascending)
      .offset((page - 1) * per)
      .limit(per)
      .all()

    // 构建响应数据
    let response = PaginatedTranscriptResponse(
      items: transcripts,
      metadata: .init(
        page: page,
        per: per,
        total: total
      )
    )

    // 缓存结果（设置24小时过期）
    do {
      try await req.cache.set(
        response,
        forKey: cacheKey,
        duration: CacheConfig.Duration.medium,
        type: .transcript,
        on: req.redis
      )
    } catch {
      req.logger.error("getTranscriptByAudio 缓存存储失败: \(error)")
    }

    return response
  }

  // 提交字幕反馈
  struct TranscriptFeedbackRequest: Content {
    let types: [Feedback.FeedbackType]
    let content: String?
  }

  @Sendable
  func submitTranscriptFeedback(req: Request) async throws -> BasicResponse {
    let userID = try req.authenticatedUserID

    guard let audioID = req.parameters.get("audioID", as: UUID.self) else {
      throw Abort(.badRequest, reason: "Invalid audio ID")
    }

    // 检查是否是系统音频
    let systemAudioID = UUID(uuidString: "00000000-0000-0000-0000-000000000000")!
    if audioID == systemAudioID {
      throw Abort(.notFound, reason: "Audio not found")
    }

    let feedbackRequest = try req.content.decode(TranscriptFeedbackRequest.self)

    // 验证反馈类型是否都是字幕相关的
    for type in feedbackRequest.types {
      switch type {
      case .spellingError, .translationError, .timingIssue, .missingContent, .otherIssue:
        continue
      default:
        throw Abort(.badRequest, reason: "Invalid feedback type for transcript")
      }
    }

    // 验证音频是否存在
    guard try await Audio.find(audioID, on: req.db) != nil else {
      throw Abort(.notFound, reason: "Audio not found")
    }

    // 为每种反馈类型创建一条反馈记录
    var lastFeedbackID: UUID?

    for type in feedbackRequest.types {
      let feedback = Feedback(
        reporterID: userID,
        category: .contentIssue,
        type: type,
        content: feedbackRequest.content,
        status: .pending,
        audioID: audioID
      )

      try await feedback.save(on: req.db)
      lastFeedbackID = feedback.id
    }

    return BasicResponse(
      success: true,
      message: "反馈提交成功",
      id: lastFeedbackID
    )
  }
}
